package com.tzt.autotask;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tzt.contents.CacheKeyConstant;
import com.tzt.contents.Constantpool;
import com.tzt.contents.ErrorCodeConstant;
import com.tzt.dao.*;
import com.tzt.entity.*;
import com.tzt.exception.InnerException;
import com.tzt.sms.EnsmsSend;
import com.tzt.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Double
 */
@Component
public class TerminalAutotask
{

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private GetCacheUtil getCacheUtil;

    @Resource
    private TerminalMapper terminalMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private OrderBackupMapper orderBackupMapper;

    @Resource
    private MessagePushLogMapper messagePushLogMapper;

    @Resource
    private MessageTempletMapper messageTempletMapper;

    @Autowired
    private EnsmsSend ensmsSend;

    @Resource
    private NotifierMsgTempletMapper notifierMsgTempletMapper;

    @Resource
    private NotifierMapper notifierMapper;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private TerminalHistoryMapper terminalHistoryMapper;

    @Resource
    private BoxMerchandiseMapper boxMerchandiseMapper;

    @Resource
    private InventoryReportMapper inventoryReportMapper;

    @Resource
    private InventoryReportDetailMapper inventoryReportDetailMapper;

    @Resource
    private InventoryWarningRulesMapper inventoryWarningRulesMapper;

    @Resource
    private InventoryWarningTerminalMapper inventoryWarningTerminalMapper;

    @Resource
    private CameraDeviceMapper cameraDeviceMapper;

    @Resource
    private ShopUserMapper shopUserMapper;

    /**
     * <功能详细描述>定时更新终端状态
     *
     * @see [类、类#方法、类#成员]
     */
    @Scheduled (cron = "0 */10 * * * ?")
    public void terminalStatus()
    {
        logger.info("定时更新终端状态");
        List<TerminalEntity> terminalAll = terminalMapper
                .getTerminalAllIsBind();
        if (NomalUtil.isNullOrEmpty(terminalAll))
        {
            return;
        }
        String shutdownMessageId = getCacheUtil.getDictValueByKey(Constantpool.DICT_SHUTDOWN_MESSAGE_ID);
        List<NotifierMsgTempletEntity> selectByMessageTempletId = notifierMsgTempletMapper.selectByMessageTempletId(Integer.valueOf(shutdownMessageId));
        MessageTempletEntity messageTemplet = messageTempletMapper.getMessageTemplet(Integer.valueOf(shutdownMessageId));
        for (TerminalEntity entity : terminalAll)
        {
            TerminalEntity obj = (TerminalEntity) getCacheUtil.getObjRedisVal(
                    CacheKeyConstant.SHOP_TERMINAL_STATUS + entity.getSerialNumber());
            if (NomalUtil.isNullOrEmpty(obj))
            {

                TerminalEntity terminalBySerialNumber = terminalMapper.getTerminalBySerialNumber(entity.getSerialNumber());
                if (terminalBySerialNumber.getStatus() == 1)
                {
                    // 已关机
                    continue;
                }
                // 新增终端下线记录
                TerminalHistoryEntity terminalHistory=new TerminalHistoryEntity();
                terminalHistory.setTerminalId(terminalBySerialNumber.getId());
                terminalHistory.setSerialNumber(entity.getSerialNumber());
                terminalHistory.setStatus(1);
                terminalHistory.setTerminalDescribe("设备下线");
                terminalHistoryMapper.insertTerminalHistory(terminalHistory);
                logger.info("终端关机" + terminalBySerialNumber.getSerialNumber());
                TerminalEntity updateEntity = new TerminalEntity();
                updateEntity.setId(entity.getId());
                updateEntity.setStatus(1);
                terminalMapper.updateTerminalById(updateEntity);
                getCacheUtil.setTerminalHandle(entity.getSerialNumber(), null);
                try{
                    Map<String, String> param = new HashMap<String, String>();
                    String custoerToken = MD5Util.MD5(
                            Constantpool.PLATFORM_CUSTOMER_SALT+"_"+entity.getSerialNumber());
                    param.put("custoerToken",custoerToken);
                    param.put("status","1");
                    param.put("serialNumber",entity.getSerialNumber());
                    HttpClientUtil.doGet(null,getCacheUtil.getDictValueByKey(Constantpool.DICT_PLATFORM_DNS)
                            +getCacheUtil.getDictValueByKey(Constantpool.DICT_UPDATE_PLATFORM_STATUS),param);
                    logger.info("向平台上报终端下线serialNumber："+entity.getSerialNumber());
                }catch (Exception e){
                    logger.info("平台上报失败："+e);
                }
                for (NotifierMsgTempletEntity notifierMsgTempletEntity : selectByMessageTempletId)
                {
                    NotifierEntity notifier = notifierMapper.selectNotifier(
                            notifierMsgTempletEntity.getNotifierId());
                    logger.info("终端关机发送短信" + notifier.getMobile());
                    // 短信内容
                    String content = messageTemplet.getContent();
                    content = content.replace("@",
                            terminalBySerialNumber.getId().toString());
                    Map<String, String> map = getCacheUtil.getSmsInfo();
                    ensmsSend.sendSms(map, notifier.getMobile(), content);
                    insertMessagePushLog(
                            terminalBySerialNumber.getSerialNumber(),
                            notifier.getId(), notifier.getName(), null,
                            notifier.getMobile(), messageTemplet.getId(),
                            messageTemplet.getTitle(), content, 1);
                }
            }

        }

    }

    @Scheduled (cron = "0 */30 * * * ?")
    public void cameraStatus()
    {
        logger.info("定时更新摄像头状态");
        List<CameraDeviceEntity> list = cameraDeviceMapper.getOnlineCamera();
        for(CameraDeviceEntity entity : list){
            CameraDeviceEntity cameraDeviceInfo = (CameraDeviceEntity) getCacheUtil.getObjRedisVal(CacheKeyConstant.SHOP_TERMINAL_STATUS + entity.getCameraMarker());
            if(NomalUtil.isNullOrEmpty(cameraDeviceInfo)){
                // TODO 是否需要短信通知
                CameraDeviceEntity updateEntity = new CameraDeviceEntity();
                updateEntity.setId(entity.getId());
                updateEntity.setStatus(0);
                cameraDeviceMapper.updateByPrimaryKeySelective(updateEntity);
                try{
                    // 上报平台
                    Map<String, String> paramMap = new HashMap<String, String>();
                    paramMap.put("cameraMarker", entity.getCameraMarker());
                    paramMap.put("status", "0");
                    // 向平台报备绑定，入参 cameraMarker,serialNumber
                    HttpClientUtil.doPost(getCacheUtil.getDictValueByKey(Constantpool.DICT_PLATFORM_DNS) +
                            getCacheUtil.getDictValueByKey(Constantpool.DICT_UPDATE_CAMERA_STATUS),paramMap);
                    logger.info("向平台上报摄像头下线：" + entity.getCameraMarker());
                }catch (Exception e){
                    logger.info("摄像头平台上报失败："+e);
                }
            }
        }
    }

    private void insertMessagePushLog(String serialNumber, int notifierId,
            String notifierName, String email, String mobile,
            int messageTempletId, String title, String content, int type)
    {
        MessagePushLogEntity entity = new MessagePushLogEntity();
        entity.setSerialNumber(serialNumber);
        entity.setNotifierId(notifierId);
        entity.setNotifierName(notifierName);
        entity.setMobile(mobile);
        entity.setMessageTempletId(messageTempletId);
        entity.setTitle(title);
        entity.setContent(content);
        entity.setType(type);
        messagePushLogMapper.insertMessagePushLog(entity);
    }

    /**
     * 定时更新经纬度 <功能详细描述>
     *
     * @see [类、类#方法、类#成员]
     */
    @Scheduled (cron = "0 0 8,12,14,18,22 * * ?")
    // @Scheduled(cron = "0 */1 * * * ?")
    public void terminalStatusLatAndlong()
    {
        logger.info("定时更新经纬度");
        try
        {
            List<TerminalEntity> terminalAll = terminalMapper
                    .getTerminalAll(null);
            if (NomalUtil.isNullOrEmpty(terminalAll))
            {
                return;
            }
            for (TerminalEntity entity : terminalAll)
            {
                TerminalEntity redisEntity = (TerminalEntity) getCacheUtil
                        .getObjRedisVal(
                                CacheKeyConstant.SHOP_TERMINAL_STATUS + entity
                                        .getSerialNumber());
                if (NomalUtil.isNullOrEmpty(redisEntity))
                {
                    continue;
                }
                if (NomalUtil.isNull(redisEntity.getLatitude(),
                        redisEntity.getLongitude()))
                {
                    continue;
                }
                TerminalEntity updateEntity = new TerminalEntity();
                updateEntity.setId(entity.getId());
                Map<String, Object> translate = translate(
                        redisEntity.getLatitude(), redisEntity.getLongitude());
                updateEntity.setLatitude(translate.get("lat").toString());
                updateEntity.setLongitude(translate.get("lng").toString());
                terminalMapper.updateTerminalById(updateEntity);
            }
        }
        catch (Exception e)
        {
            logger.error("terminalStatus is error:" + new Date(), e);
        }

    }

    /**
     * 转换经纬度 <功能详细描述>
     *
     * @param lat
     * @param lng
     * @return
     * @see [类、类#方法、类#成员]
     */
    private Map<String, Object> translate(String lat, String lng)
            throws InnerException
    {
        Map<String, String> map = new HashMap<String, String>();
        String locations = lat + "," + lng;
        System.out.println(locations + "11111111111111111111");
        map.put("locations", locations);
        map.put("type", "1");// 输入的locations的坐标类型,可选值为[1,6]之间的整数，每个数字代表的类型说明： 1
        // GPS坐标、2 sogou经纬度、3 baidu经纬度、4 mapbar经纬度、5
        // [默认]腾讯、google、高德坐标、6 sogou墨卡托
        map.put("key", "74JBZ-WEQR5-S4FIK-Q5ISS-BEDU2-EBBH5");
        String doGet = null;
        try{
            doGet = HttpClientUtil
                    .doGet(null,"http://apis.map.qq.com/ws/coord/v1/translate", map);
        }catch (Exception e){
            throw new InnerException(ErrorCodeConstant.FAILED, "经纬度转换失败！");
        }

        JSONObject sobj = new JSONObject();
        sobj = JSONObject.parseObject(doGet);
        JSONArray geocodes = sobj.getJSONArray("locations");
        JSONObject trueAddress = geocodes.getJSONObject(0);
        Map<String, Object> resultMap = JsonUtil
                .convertMapByJson(trueAddress.toJSONString());
        // System.out.println(resultMap.get("lng"));
        // System.out.println(resultMap.get("lat"));
        return resultMap;
    }

    /**
     * <功能详细描述>每天18：00，查询有未支付订单，直接微信消息提醒用户支付
     *
     * @see [类、类#方法、类#成员]
     */
    @Scheduled (cron = "0 0 18 * * ?")
//      @Scheduled(fixedDelay=1000)
    public void receiveNotification()
    {

        List<OrderEntity> weixinNotPay = orderMapper.getWeixinNotPay();
        if (NomalUtil.isNullOrEmpty(weixinNotPay))
        {
            return;
        }
        List<NotificationEntity> notificationList = new ArrayList<NotificationEntity>();
        for (OrderEntity orderEntity : weixinNotPay)
        {
            NotificationEntity notificationEntity = new NotificationEntity();
            List<OrderDetailEntity> orderDetail = orderDetailMapper
                    .getOrderByOrderId(orderEntity.getId());
            if (NomalUtil.isNullOrEmpty(orderDetail))
            {
                continue;
            }
            notificationEntity.setOpenid(orderEntity.getOpenid());
            notificationEntity.setTotalAmaount(orderEntity.getDiscountOrderAmount());
            notificationEntity.setPrepayId(orderEntity.getTradeNo());
            notificationEntity.setOrderNumber(orderEntity.getOrderNumber());
            notificationEntity.setOrderBuyTime(DateUtil.dateToStrLong(orderEntity.getCreatedAt()));
            notificationEntity.setOrderTradeName(getOrderTradeName(orderDetail));
            notificationList.add(notificationEntity);
        }
        JSONObject jobj = new JSONObject();
        jobj.put("type", "notPayOrder");
        jobj.put("notificationList", notificationList);
        try
        {
            logger.info("未支付订单通知开始");
            Map<String, Object> params = HttpClientUtil.doPost(null, jobj,
                    getCacheUtil.getDictValueByKey(Constantpool.DICT_SERVICE_DOMAIN_NAME) + getCacheUtil.getDictValueByKey
                            (Constantpool.DICT_RECEIVE_NOTIFICATION));
            if (!"0".equals(params.get("code").toString()))
            {
                return;
            }
            logger.info("未支付订单通知结束");
        }
        catch (Exception e)
        {
            logger.info("未支付订单通知错误" + e);
        }
    }

    private String getOrderTradeName(List<OrderDetailEntity> orderDetail)
    {
        StringBuffer orderTradeName = new StringBuffer();
        for (OrderDetailEntity orderDetailEntity : orderDetail)
        {
            ProductEntity productInfo = getCacheUtil
                    .getProductInfo(orderDetailEntity.getProductId());
            orderTradeName.append(productInfo.getName())
                    .append(orderDetailEntity.getAmount())
                    .append(productInfo.getUnit()).append(";");
            if (orderTradeName.length() > 30)
            {
                orderTradeName = new StringBuffer(
                        orderTradeName.substring(0, 27)).append("...");
                break;
            }
        }
        return orderTradeName.toString();
    }

    @Scheduled (cron = "0 0 3 * * ?")
    public void removeOrderbackUp()
    {
        logger.info("定时任务，删除订单备份数据");
        orderBackupMapper.delOrderBackup();
    }

    //每天晚上12点插入库存报表
    @Scheduled (cron = "0 0 0 * * ?")
//    @Scheduled(fixedDelay=60000)
    public void timingInsertInventoryReport(){
        List<BoxMerchandiseEntity> terminalProductNum = boxMerchandiseMapper.getTerminalProductNum();
        for (BoxMerchandiseEntity boxMerchandiseEntity : terminalProductNum)
        {
            InventoryReportEntity entity=new InventoryReportEntity();
            entity.setTerminalId(boxMerchandiseEntity.getTerminalId());
            entity.setSerialNumber(boxMerchandiseEntity.getSerialNumber());
            entity.setTotalInventory(boxMerchandiseEntity.getTotalNum());
            //插入库存报表
            inventoryReportMapper.insertSelective(entity);
            Map<String,Object> map=new HashMap<String,Object>(16);
            map.put("inventoryReportId",entity.getId());
            map.put("terminalId",boxMerchandiseEntity.getTerminalId());
            //根据终端id添加库存报表详情
            inventoryReportDetailMapper.addInventoryReportDetailByTerminalId(map);
        }
    }

    //每天上午7天通知供应商过期的商品
//    @Scheduled (cron = "0 0 8 * * ?")
//    @Scheduled (cron = "0/20 * *  * * ?")
    public void noticeSupplierExpiryProduct(){
       try
       {
           logger.info("定时任务，发送通知供应商过期的商品开始");
           //获取当前时间
           String currentTime = DateUtil.dateToStr(new Date());
           //根据当前时间查询有过期商品的终端
           List<Integer> terminalIds = boxMerchandiseMapper.groupGetTerminalIdList(currentTime);
           Map<String,Object> qryMap =new HashMap<String,Object>();
           if (!NomalUtil.isNullOrEmpty(terminalIds)){
               for (Integer terminalId : terminalIds)
               {
                   //根据终端id查询供应商id
                   List<Integer> supplierIds = boxMerchandiseMapper.getSupplierIdsByTerminalId(terminalId);
                   if(NomalUtil.isNullOrEmpty(supplierIds)){
                       continue;
                     }
                   //查询终端资产信息信息
                   TerminalEntity terminalEntity = terminalMapper.selectTerminalInfoByTerminalId(terminalId);
                   //根据终端id查询序列号
                   String serialNumber = terminalMapper.getSerialNumberByTerminalId(terminalId);
                   for (Integer supplierId : supplierIds)
                   {
                       //查询供应商信息
                       ShopUserEntity shopUserEntityById = shopUserMapper.getShopUserEntityById(supplierId);
                       if(NomalUtil.isNull(shopUserEntityById.getOpenid())){
                           continue;
                       }
                       qryMap.put("terminalId",terminalId);
                       qryMap.put("supplierId",supplierId);
                       qryMap.put("currentTime",currentTime);
                       List<ProductEntity> productList = productMapper.getTerminalExpiryProduct(qryMap);
                       qryMap.clear();
                       JSONObject jobj = new JSONObject();
                       jobj.put("type", "receivingExpiryNotification");
                       jobj.put("currentTime",currentTime);
                       jobj.put("productList",productList);
                       jobj.put("terminalName",terminalEntity.getTerminalName());
                       jobj.put("releasePointName",terminalEntity.getName());
                       jobj.put("openid",shopUserEntityById.getOpenid());
                       jobj.put("serialNumber",serialNumber);
                       jobj.put("address",terminalEntity.getAddress());
//                       System.out.println(jobj.toString());
//                       logger.info("过期商品通知供应商开始");
//                       Map<String, Object> params = HttpClientUtil.doPost(null, jobj,
//                               getCacheUtil.getDictValueByKey(Constantpool.DICT_SERVICE_DOMAIN_NAME) + getCacheUtil.getDictValueByKey
//                                       (Constantpool.DICT_RECEIVING_EXPIRY_NOTIFICATION));
//                       if (!"0".equals(params.get("code").toString()))
//                       {
//                           return;
//                       }
                       logger.info("过期商品通知供应商结束");
                   }
               }
           }
       }catch (Exception e){
           e.printStackTrace();
           logger.info("定时任务，发送通知供应商过期的商品失败");
       }
    }
}
